from django.core.mail import send_mail
from rest_framework import serializers
from .models import User, Address
import re
from django_redis import get_redis_connection
from rest_framework_jwt.settings import api_settings

from celery_tasks.email.tasks import send_verify_email
from goods.models import SKU


class CreateUserSerializers(serializers.ModelSerializer):
    # 所有字段 ['id', 'username', 'mobile', 'password', 'password_verified', 'sms_code', 'allow']
    # 存入数据库 [id, username, mobile, password]
    # 序列化字段 [id, username, mobile, token]
    # 反序列化 [username, mobile, password, password_verified, sms_code, allow]
    password_verified = serializers.CharField(label="确认密码", write_only=True)
    sms_code = serializers.CharField(label="验证码", write_only=True)
    allow = serializers.CharField(label="是否同意协议", write_only=True)
    token = serializers.CharField(label="token", read_only=True)

    class Meta:
        model = User
        # 映射模型中需要序列化的字段
        fields = ['id', 'username', 'mobile', 'password', 'password_verified', 'sms_code', 'allow', 'token']
        extra_kwargs = {
            'username': {
                'min_length': 5,
                'max_length': 15,
                'error_messages': {
                    'min_length': '仅允许5-15个字符的用户名',
                    'max_length': '仅允许5-15个字符的用户名'
                }
            },
            'password': {
                'write_only': True,
                'min_length': 5,
                'max_length': 20,
                'error_messages': {
                    'min_length': '密码长度为5-20个字符，由字母、数字、下划线组成',
                    'max_length': '密码长度为5-20个字符，由字母、数字、下划线组成',
                }
            }
        }

    # 校验手机号
    def validate_mobile(self, value):
        if not re.match(r'1[3-9]\d{9}$', value):
            raise serializers.ValidationError('手机号格式不正确!')
        return value

    # allowed
    def validate_allow(self, value):
        if value != 'true':
            raise serializers.ValidationError('请勾选用户协议')
        return value

    def validate(self, attrs):
        # 校验密码
        if attrs['password'] != attrs['password_verified']:
            raise serializers.ValidationError('两次输入的密码不相同')
        # 验证码
        redis_conn = get_redis_connection('default')
        mobile = attrs.get('mobile')
        real_sms_code = redis_conn.get('sms_%s' % mobile)
        # 判断验证码在redis中是否存在，或者和前端传入的验证码是否相等
        if real_sms_code is None or attrs.get('sms_code') != real_sms_code.decode():
            raise serializers.ValidationError('请输入正确的验证码！')
        return attrs

    def create(self, validated_data):
        # 移除不需要存储的字段
        del validated_data['password_verified']
        del validated_data['sms_code']
        del validated_data['allow']
        # 加密密码
        password = validated_data.pop('password')
        # 给模型对象赋值(username,mobile)
        user = User(**validated_data)
        # password加密后赋值给User模型
        user.set_password(password)
        user.save() # 存储到数据库
        # print(validated_data)

        # 生成token
        jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER  # 引用jwt中的叫jwt_payload_handler函数(生成payload)
        jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER  # 函数引用 生成jwt

        payload = jwt_payload_handler(user)  # 根据user生成用户相关的载荷
        token = jwt_encode_handler(payload)  # 传入载荷生成完整的jwt

        user.token = token  # 将token加入到响应对象中
        return user


class UserCenterDetailserializers(serializers.ModelSerializer):
    """用户详情序列化器"""
    class Meta:
        model = User
        fields = ['id', 'username', 'email', 'mobile', 'email_active']


class UserCenterDetailsEmailSerializers(serializers.ModelSerializer):
    """邮箱验证"""
    class Meta:
        model = User
        fields = ['id', 'email']
        extra_kwargs = {
            'email': {
                'required': True
            }
        }

    def update(self, instance, validated_data):
        # 重写update方法，方便发送验证邮件
        instance.email = validated_data.get('email')
        instance.save()
        # ZOKTJRXFLMWVWJUT
        # 发送邮件
        verify_url = instance.generate_email_verify_url()
        print(verify_url)
        send_verify_email.delay(instance.email, verify_url=verify_url)

        # subject = "美多商城邮箱验证"  # 邮件主题/标题
        # html_message = '<p>尊敬的用户您好！</p>' \
        #                '<p>感谢您使用美多商城。</p>' \
        #                '<p>您的邮箱为：%s 。请点击此链接激活您的邮箱：</p>' \
        #                '<p><a href="%s">%s<a></p>' % (instance.email, verify_url, verify_url)
        #
        # send_mail(subject, '', 'django<wdeua30133@163.com>', [instance.email], html_message=html_message)

        return instance


class UserAddressSerializer(serializers.ModelSerializer):
    """用户收货地址序列化器"""
    province = serializers.StringRelatedField(read_only=True)
    city = serializers.StringRelatedField(read_only=True)
    district = serializers.StringRelatedField(read_only=True)
    province_id = serializers.IntegerField(required=True, label='省ID')
    city_id = serializers.IntegerField(required=True, label='市ID')
    district_id = serializers.IntegerField(required=True, label='区ID')

    class Meta:
        model = Address
        # 排除不需要参与序列化和反序列化的字段
        exclude = ('user', 'create_time', 'update_time', 'is_deleted')

    def validate_mobile(self, value):
        if not re.match(r'1[3-9]\d{9}', value):
            raise serializers.ValidationError('手机号格式不正确！')
        return value

    def create(self, validated_data):
        user = self.context['request'].user  # 获取用户模型对象
        print('user', user)
        validated_data['user'] = user
        return Address.objects.create(**validated_data)


class AddressTitleSerializer(serializers.ModelSerializer):
    class Meta:
        model = Address
        fields = ['title']


class UserBrowserHistorySaveSerializer(serializers.Serializer):
    """用户商品浏览记录保存序列化器"""
    sku_id = serializers.IntegerField(label='商品ID', min_value=1)

    def validate_sku_id(self, value):
        try:
            SKU.objects.get(id=value)
        except SKU.DoesNotExist:
            raise serializers.ValidationError('此商品id不存在！')
        return value

    def create(self, validated_data):
        sku_id = validated_data.get('sku_id')

        # 获取用户模型
        user = self.context['request'].user
        # 存储到redis中的key值
        history_key = 'history_{}'.format(user.id)
        # sku_id 保存到redis（List类型）需要去重，排序
        redis_conn = get_redis_connection('default')
        pl = redis_conn.pipeline()

        # 去重
        pl.lrem(history_key, 0, sku_id)

        # 后加的值排到list的开头
        pl.lpush(history_key, sku_id)

        # 截取前5个值
        pl.ltrim(history_key, 0, 4)

        pl.execute()

        return validated_data


class UserBrowserHistoryDisplaySerializer(serializers.ModelSerializer):
    """展示用户浏览记录序列化器"""
    class Meta:
        model = SKU
        fields = ['id', 'name', 'price', 'default_image_url', 'comments']